OmniDesignerCustomLabelDeployer

Print
Visualforce Page Details
Name OmniDesignerCustomLabelDeployer
Label OmniScript Designer Custom Label Deployer
Namespace Prefix omnistudio
Api Version 60
Markup <apex:page showHeader="false" sidebar="false" standardStylesheets="false" docType="html-5.0" applyBodyTag="false" lightningStylesheets="false" applyHtmlTag="false" title="OmniScript Compiler VF Page" cache="false" controller="omnistudio.OmniScriptDesignerController" action="{!checkIfOmniDesignCustomLabelDeployerThisIsFirstInstalledPackage}"> <html xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" lang="en"> <head> <meta http-equiv="x-ua-compatible" content="ie=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <script src="{!URLFOR($Resource.jsforce_1_7, '/jszip.min.js')}"></script> <script src="{!URLFOR($Resource.jsforce_1_7, '/jsforce-core.min.js')}"></script> <script src="{!URLFOR($Resource.jsforce_1_7, '/jsforce-api-tooling.min.js')}"></script> <script src="{!URLFOR($Resource.jsforce_1_7, '/jsforce-api-metadata.min.js')}"></script> <script src="{!URLFOR($Resource.vlocity_core_assets, '/latest/vlocity_core_assets.js')}"></script> <script type="text/javascript"> window.conn = new jsforce.Connection({ accessToken: '{!vlocAccessToken}', version: '60.0' }); conn.metadata.pollTimeout = 600000; // 10 minute polling timeout const POST_MESSAGE_KEY = '{!JSENCODE($CurrentPage.parameters.postmessagekey)}'; </script> </head> <body> <p id="deployment-message"></p> <script> let allUnmanagedLabels = null; const messageEl = document.getElementById('deployment-message'); loadAllCustomLabelsInOrg(); window.addEventListener("message", (event) => { let params = (new URL(document.location)).searchParams; const eventUrl = new URL(event.origin); const expectedUrl = new URL(params.get('sfdcIFrameOrigin')); if (eventUrl.hostname === expectedUrl.hostname && eventUrl.protocol === expectedUrl.protocol && event.data.message === 'saveLabels') { saveAll(event.data.labels) .then(complete => { setMessage(false, complete); }) .catch(err => { setMessage(true, err); }) } }, false); function saveAll(arrayOfLabels) { if (!allUnmanagedLabels) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(saveAll(arrayOfLabels)); }, 1000); }); } var arrayToUpsert = [], arrayToDeploy = []; arrayOfLabels.forEach((label) => { if (label.value === null || label.value === undefined) { return; } // Do a metadata deploy instead of upsert if this label is from a managed // package. if (/__/.test(label.name)) { arrayToDeploy.push(label); return; } const existingLabel = allUnmanagedLabels[label.name.toLowerCase()]; // change the name to match the case sensitive version of the existing one // otherwise we'll get a duplicate error if (existingLabel) { label.name = existingLabel.originalName; } // Do a metadata deploy instead of upsert if the label exists // but this is a different language. if (existingLabel && existingLabel.originalLanguage !== label.language) { arrayToDeploy.push(label); return; } // Don't do anything if the language and label value are the same if (existingLabel && existingLabel.originalLanguage === label.language && existingLabel.value === label.value) { return; } arrayToUpsert.push(label); }); const promiseToUpsert = upsertAll(_.uniqBy(arrayToUpsert, 'name')); const promiseToDeploy = deployAll(_.uniqBy(arrayToDeploy, 'name')); return Promise.all([promiseToUpsert, promiseToDeploy]); } function upsertAll(arrayOfLabels) { if (!arrayOfLabels || arrayOfLabels.length === 0) { return Promise.resolve(true); } // Metadata api only accepts 10 inserts at a time, so split // up larger arrays into multiple smaller ones and submit individually if (arrayOfLabels.length > 10) { const maxSizeTenArrays = []; while (arrayOfLabels.length > 0) { maxSizeTenArrays.push(arrayOfLabels.splice(0, 10)); } return Promise.all(maxSizeTenArrays.map((arrayOfLabels) => { return upsertAll(arrayOfLabels); })); } var metadata = arrayOfLabels.map((label) => { return { fullName: label.name, language: label.language, protected: false, shortDescription: label.shortDescription, value: label.value }; }); return new Promise((resolve, reject) =>{ conn.metadata.upsert('CustomLabel', metadata, (err, results) => { if (err) { reject(err); return; } if (!Array.isArray(results)) { results = [results]; } const errors = results.filter((result) =>{ return result.errors; }).map((result) => { return result.errors; }); if (errors.length > 0) { reject(errors); return; } resolve(results[0]); }); }); } function deployAll(arrayOfLabels) { if (!arrayOfLabels || arrayOfLabels.length === 0) { return Promise.resolve(true); } return createZipOfAll(arrayOfLabels) .then((zipStream) => { return new Promise((resolve, reject) => { conn.metadata.deploy(zipStream, { singlePackage: true }) .complete((err, deployResult) => { if (err) { reject(err); return; } if (deployResult.success === false) { conn.metadata.checkDeployStatus(deployResult.id, true, (err, result) => { console.log(err); console.log(result); }); reject(deployResult); return; } resolve(deployResult); }); }); }); } function createZipOfAll(arrayOfLabels) { return new Promise((resolve, reject) => { const zip = new JSZip(); const langToLabelsMap = arrayOfLabels.reduce((map, label) => { if (!map[label.language]) { map[label.language] = []; } map[label.language].push(label); return map; }, {}); zip.file( 'package.xml', '<?xml version=\"1.0\" encoding=\"UTF-8\"?>' + '<Package xmlns=\"http://soap.sforce.com/2006/04/metadata\">' + '<types>' + '<members>*</members>' + '<name>CustomLabels</name>' + '</types>' + '<types>' + Object.keys(langToLabelsMap) .map((language) => { return '<members>' + language + '</members>'; }) .join('') + '<name>Translations</name>' + '</types>' + '<version>42.0</version>' + '</Package>' ); Object.keys(langToLabelsMap) .forEach((language) => { const languageLabels = langToLabelsMap[language]; const languageLabelsXml = arrayOfLabels.map((label) => { return '<customLabels>' + '<label>' + label.value + '</label>' + '<name>' + label.name + '</name>' + '</customLabels>'; }); // translation file zip.file( 'translations/' + language + '.translation', '<?xml version=\"1.0\" encoding=\"UTF-8\"?>' + '<Translations xmlns=\"http://soap.sforce.com/2006/04/metadata\">' + languageLabelsXml + '</Translations>' ); }); var content = zip.generateAsync({type: 'base64'}) .then((content) => { resolve(content); }); }); } function setMessage(isError, message) { messageEl.innerText = message; window.parent.postMessage({ key: POST_MESSAGE_KEY, err: isError ? message : undefined, response: isError ? undefined : message }, '*'); } function loadAllCustomLabelsInOrg() { allUnmanagedLabels = null; conn.metadata.retrieve({ unpackaged: { 'types': { 'members': '*', 'name': 'CustomLabel' }, 'version': '42.0' } }).complete((err, result) => { JSZip.loadAsync(result.zipFile, {base64: true}) .then((zip) => { if (zip.files['unpackaged/labels/CustomLabels.labels']) { const outputFile = zip.file('unpackaged/labels/CustomLabels.labels'); if (outputFile) { return outputFile.async('string'); } } return Promise.resolve('<?xml version=\"1.0\" ' + 'encoding=\"UTF-8\"?><CustomLabels xmlns=\"http://soap.sforce.com/2006/04/metadata\">' + '</CustomLabels>'); }).then((text) => { const jsonResponse = xmlToJson(text); let labels = jsonResponse.CustomLabels.labels; if (!Array.isArray(labels) && labels) { labels = [labels]; } if (!labels) { allUnmanagedLabels = {}; return; } allUnmanagedLabels = labels.reduce(function (obj, label) { if (!obj[label.fullName['#text'].toLowerCase()]) { obj[label.fullName['#text'].toLowerCase()] = {}; } obj[label.fullName['#text'].toLowerCase()] = { originalName: label.fullName['#text'], originalLanguage: label.language['#text'], isDefault: true, value: label.value['#text'] }; return obj; }, {}); }); }); } function xmlToJson(xmlString) { let xml = xmlString; if (xml == null) { return {}; } if (typeof xmlString === 'string') { const oParser = new DOMParser(); xml = oParser.parseFromString(xmlString, 'text/xml'); if (isParseError(xml)) { return {}; } } // Create the return object let obj = {}; if (xml.nodeType === 1) { // element processXmlAttributes(xml, obj); } else if (xml.nodeType === 3) { // text obj = xml.nodeValue; } // do children if (xml.hasChildNodes()) { processChildNodes(xml, obj); } return obj; } function processXmlAttributes(xml, obj) { if (xml.attributes.length > 0) { for (let j = 0; j < xml.attributes.length; j++) { const attribute = xml.attributes.item(j); obj['@' + attribute.nodeName] = attribute.nodeValue; } } } function processChildNodes(xml, obj) { for (let i = 0; i < xml.childNodes.length; i++) { const item = xml.childNodes.item(i); const nodeName = item.nodeName; if (typeof (obj[nodeName]) === 'undefined') { obj[nodeName] = xmlToJson(item); } else { if (typeof (obj[nodeName].push) === 'undefined') { var old = obj[nodeName]; obj[nodeName] = []; obj[nodeName].push(old); } obj[nodeName].push(xmlToJson(item)); } } } function isParseError(parsedDocument) { // parser and parsererrorNS could be cached on startup for efficiency var parser = new DOMParser(), errorneousParse = parser.parseFromString('<', 'text/xml'), parsererrorNS = errorneousParse.getElementsByTagName('parsererror')[0].namespaceURI; if (parsererrorNS === 'http://www.w3.org/1999/xhtml') { // In PhantomJS the parseerror element doesn't seem to have a special // namespace, so we are just guessing here :( return parsedDocument.getElementsByTagName('parsererror').length > 0; } return parsedDocument.getElementsByTagNameNS(parsererrorNS, 'parsererror').length > 0; } </script> </body> </html> </apex:page>